const swig = require('swig')
const fs = require('fs')
const path = require('path')
const glob = require('glob')
const useref = require('useref')

const menus = [{
    name: 'Home',
    icon: 'aperture',
    link: 'index.html'
  },
  {
    name: 'Features',
    link: 'features.html'
  },
  {
    name: 'About',
    link: 'about.html'
  },
  {
    name: 'Contact',
    link: '#',
    children: [{
        name: 'Twitter',
        link: 'https://twitter.com/w_zce'
      },
      {
        name: 'About',
        link: 'https://weibo.com/zceme'
      },
      {
        name: 'divider'
      },
      {
        name: 'About',
        link: 'https://github.com/zce'
      }
    ]
  }
]

module.exports = grunt => {
  grunt.initConfig({
    // 清除生成文件
    clean: {
      temp: 'dist/**/*'
    },
    // 处理sass文件
    sass: { // Task
      dist: { // Target
        options: {
          style: 'expanded',
          sourceMap: false,
        },
        files: [{
          expand: true,
          cwd: 'src',
          src: ['assets/styles/*.scss'],
          dest: 'dist',
          ext: '.css'
        }]
      }
    },
    // babel编译js代码
    babel: {
      options: {
        sourceMap: false,
        presets: ['@babel/preset-env']
      },
      dist: {
        files: [{
          expand: true,
          cwd: 'src',
          src: ['assets/scripts/*.js'],
          dest: 'dist',
          ext: '.js'
        }]
      }
    },
    // 处理压缩图片
    imagemin: {
      dynamic: {
        files: [{
          expand: true,
          cwd: 'src',
          src: ['assets/{images,fonts}/*.{png,jpg,gif,svg}'],
          dest: 'dist'
        }]
      }
    },
    // 拷贝字体文件和public里的文件
    copy: {
      main: {
        expand: true,
        cwd:'src/',
        src: 'assets/fonts/*.{eot,ttf,woff}',
        dest: 'dist/',
      },
      public: {
        expand: true,
        src: './public/*',
        dest: 'dist/',
      }
    },
    watch: {
      js: {
        files: ['src/assets/scripts/*.js'],
        tasks: ['babel']
      },
      sass: {
        files: ['src/assets/styles/*.scss'],
        tasks: ['sass']
      },

      html: {
        files: ['src/*.html'],
        tasks: ['swig']
      }
    },
    // 开发环境 在浏览器中预览，修改代码可自动刷新页面
    browserSync: {
      dev: {
        options: {
          open: false,
          notify: false,
          watchTask: true,
          files: [`dist/**/*`, 'assets/{images,fonts}/*', 'src/public/**'],
          server: {
            baseDir: ['dist', 'src', '.']
          }
        }
      }
    },
    // 压缩代码
    // js代码压缩
    uglify:{
      my_target:{
        files: [{
          expand: true,
          src: ['assets/scripts/*.js'],
          dest: 'dist',
          cwd: 'dist'
        }]
      }
    },
    // html压缩
    htmlmin:{
      dist: {                                      // Target
        options: {                                 // Target options
          collapseWhitespace: true,
          minifyCSS: true,
          minifiJS: true
        },
        files: [{
          expand: true,
          src: ['*.html'],
          dest: 'dist',
          cwd: 'dist'
        }]
      }
    },
    cssmin:{
      target:{
        files: [{
          expand: true,
          src: ['assets/styles/*.css'],
          dest: 'dist',
          cwd: 'dist'
        }]
      }
    }
  })
  grunt.registerTask('page', function () {
    resovlePage({
      dest: 'dist/',
      cwd: 'src/',
      src: '*.html'
    })
  })
  grunt.registerTask('useref', () => {
    const htmlFiles = glob.sync('dist/*.html')
    htmlFiles.forEach(file => {
      const inputHtml = fs.readFileSync(file, 'utf-8')
      let res = useref(inputHtml)
      fs.writeFileSync(file,res[0],'utf-8')
      if (res.length >= 2) {
        res = res[1]
        for (let k in res) {
          for (let output in res[k]) {
            const assets = res[k][output].assets
            replaceNodeodulePath(assets)
            mergeFileSync(assets,'dist/'+output)
          }
        }
      }
    })
  })

  // 清除上次生成的文件目录
  grunt.loadNpmTasks('grunt-contrib-clean')
  // 编译sass和es6
  grunt.loadNpmTasks('grunt-contrib-sass')
  grunt.loadNpmTasks('grunt-babel')
  // 压缩图片
  grunt.loadNpmTasks('grunt-contrib-imagemin')
  // 开发环境打开浏览器调试用
  grunt.loadNpmTasks('grunt-browser-sync')
  // 开发环境监听文件变化
  grunt.loadNpmTasks('grunt-contrib-watch')
  // 拷贝字体文件等
  grunt.loadNpmTasks('grunt-contrib-copy')
  // 压缩代码
  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-contrib-htmlmin')
  grunt.loadNpmTasks('grunt-contrib-cssmin')

  grunt.registerTask('dev', ['sass', 'babel', 'page', 'browserSync', 'watch'])

  grunt.registerTask('mini', ['uglify','htmlmin','cssmin'])

  grunt.registerTask('build', ['clean', 'sass', 'babel', 'imagemin', 'copy:main', 'copy:public', 'page','useref','mini'])

}


// 处理html  swig模板
function resovlePage(options) {
  const {
    dest,
    cwd,
    src
  } = options
  if (!fs.existsSync(dest)) {
    fs.mkdirSync(dest)
  }
  // 匹配所有符合条件的文件
  const srcs = glob.sync(cwd + src)
  // 分别将编译后的内容写入输出文件目录下
  srcs.forEach(item => {
    let output = path.join(dest, item.substr(cwd.length))
    let fileData = compileSwig(item)
    fs.writeFileSync(output, fileData, 'utf-8')
  })
}
// 编译swig模板
function compileSwig(path) {
  const template = swig.compileFile(path);
  const output = template({
    pkg: require('./package.json'),
    date: new Date(),
    menus: menus
  })
  return output
}
// 多个文件合并到一个文件里  同步
function mergeFileSync(input, output) {
  if (typeof input === 'string') {
    input = [input]
  }
  let outputData = ''
  let reg=/^dist/
  
  input.forEach(filepath => {
    const data = fs.readFileSync(filepath, 'utf-8')
    outputData += `${data}\n`
    // 删除合并之前在dist目录的文件
    if(reg.test(filepath)){
      fs.unlinkSync(filepath)
    }
  })
  fs.writeFileSync(output, outputData, 'utf-8')
}
// 替换 /node_modules开头引用文件路径
function replaceNodeodulePath(filePaths) {
  let reg=/^\/node_modules/
  for (let i = 0, len = filePaths.length; i < len; i++) {
    if(reg.test(filePaths[i])){
      filePaths[i] = filePaths[i].replace(/^\/node_modules/, './node_modules')
    }else{
      filePaths[i] ='dist/'+ filePaths[i]
    }
  }
}
